﻿//#define _CRT_SECURE_NO_WARNINGS
//#include <stdio.h>
//#include <iostream>
// C/C++ 学习网站：https://legacy.cplusplus.com 注意旧版本（搜索）和新版本
#include "study03.h"
//using namespace std;
using std::cout;
using std::endl;
/*
这里的指针也是点到为止。

引用：
    引用的本质是别名，它并不占用内存，而是引用另一个变量，因此引用的操作和指针的操作是类似的。
    引用的声明格式：类型别名& 引用名 = 被引用的变量名;
    引用的使用格式：引用名 = 新值;
    引用的本质是别名，因此不能对引用进行自增、自减运算。
    引用的声明和使用都不需要使用 * 运算符。
    引用的声明和使用都可以用 const、volatile 等限定符修饰。
    注意：引用相当于别名，只存在于源代码阶段，在编译后实际上并不存在，
        引用必须初始化赋值一个变量，且只能赋值变量一次不能再次修改。

指针和引用的区别：
    1. 指针可以修改它指向的变量的值，引用只能读取它指向的变量的值。
    2. 指针可以为空，引用不能为空。
    3. 指针可以直接操作内存，引用只能间接操作内存。
    4. 指针可以用 * 运算符，引用只能用 & 运算符。
    5. 指针可以用 typedef 定义别名，引用不能用 typedef 定义别名。
*/

static void print_p(int* p, int n) // 定义一个函数，参数为指针类型
{ // 打印指针 p 指向的 n 个整数
    for (int i = 0; i < n; i++)
        cout << *(p + i) << "  "; // 输出指针 p 指向的 n 个整数
    std::cout << std::endl;
}

static void add_add(int& r)
{ // 定义一个函数，参数为引用类型
    r++; // 引用 r 引用的变量的值加 1
}

void test_pointer_and_reference()
{
    { // 指针
        print_start("指针部分");
        int a1 = 0;
        int* p = &a1; // 指针变量 p 指向变量 a 的地址
        cout << "a1 的地址为：" << &a1 << endl; // 输出 a 的地址
        cout << "p 指向的地址为：" << p << endl; // 输出 p 指向的地址
        cout << "p 指向的值为：" << *p << endl; // 输出 p 指向的值
        *p = 20; // 修改 p 指向的值
        cout << "a1 的新值为：" << a1 << endl; // 输出 a 的新值

        int n = 10;
        char* chr = new char[n];
        // 申请一块内存，并将指针指向该内存，类型为 char* 相当于 C 中的 char* p = malloc(10);
        memset(chr, 'a', 10); // 用 'a' 填充内存
        cout << "chr 指向的地址为：" << chr << endl; // 输出 chr 指向的地址
        for (int i = 0; i < 10; i++)
            cout << chr[i] << "  "; // 输出 chr 指向的内存内容
        std::cout << std::endl;
        delete[] chr; // 释放内存，相当于 C 中的 free(p)，
        // 注意这里是数组，所以用 delete[] 而不是 delete;

        int arr1[5] = { 1, 2, 3, 4, 5 };
        int* parr1 = arr1; // 数组指针，指向数组 arr1 的首元素
        for (int i = 0; i < 5; i++)
            cout << parr1[i] << "  "; // 输出数组 arr1 的内容
        std::cout << std::endl;

        int arr2[5] = { 11, 12, 13, 14, 15 };
        void (*parr2)(int* p, int n) = &print_p; // 函数指针，指向函数 print_p
        parr2(arr2, 5); // 调用函数 print_p，打印数组 arr2 的内容

        int* parr[2] = { arr1, arr2 }; // 指针数组，每个元素指向一个数组
        int** p_parr = parr; // 二级指针(数组指针的指针)，指向指针数组的地址
        for (int i = 0; i < 2; i++)
        {
            for (int j = 0; j < 5; j++)
                cout << p_parr[i][j] << "  "; // 输出二级指针指向的数组内容
            std::cout << std::endl;
        }

        print_end("指针部分");
    }

    { // 引用
        print_start("引用部分");
        int a2 = 0;
        int& r = a2; // 引用变量 r 引用变量 a
        std::cout << "sizeof r = " << sizeof r << std::endl; // 输出 r 的大小
        cout << "a2 的地址为：" << &a2 << endl; // 输出 a 的地址
        cout << "r 引用的地址为：" << &r << endl; // 输出 r 引用的地址
        cout << "r 引用的值为：" << r << endl; // 输出 r 引用的值
        r = 30; // 修改 r 引用的值
        cout << "a2 的新值为：" << a2 << endl; // 输出 a 的新值

        int arr3[5] = { 6, 7, 8, 9, 10 };
        int(&r_arr3)[5] = arr3; // 引用数组，引用数组 arr1
        for (int i = 0; i < 5; i++)
            cout << r_arr3[i] << "  "; // 输出数组 arr1 的内容
        std::cout << std::endl;

        int arr4[5] = { 16, 17, 18, 19, 20 };
        void(&r_arr4)(int* p, int n) = print_p; // 引用函数，引用函数 print_p
        r_arr4(arr4, 5); // 调用函数 print_p，打印数组 arr2 的内容

        int num1 = 10;
        add_add(num1); // 调用函数 add_add，引用 num1 引用的变量的值加 1
        printf("num1 = %d\n", num1); // 输出 num1 的新值

        print_end("引用部分");
    }
}
